<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Null判断运算符</title>
  </head>
  <body>
    <script>
      // 读取对象属性的时候，如果某个属性的值是null或者undefined，有时候需要为它们指定默认值
      // 常见的做法是通过||运算符指定默认值。
      var headerText = response.settings.headerText || "Hello World!";
      var animationDuration = response.settings.animationDuration || 300;
      var showSplashScreen = response.settings.showSplashScreen || true;
      /**
       * 上面三行代码都通过 || 运算符指定默认值，但是这样写是错的。
       * 开发者的原意是，只要属性的值为null或者undefined，默认值就会生效
       * 但是属性的值如果为空串或者false或者0，默认值也会生效。
       *
       * 为了避免这种情况，ES2020引入了一个新的Null判断运算符??
       * 它的行为类似||，但是只有左侧的值为null或者undefined时，
       * 才会返回右侧的值
       */
      var headerText = response.settings.headerText ?? "Hello World!";
      var animationDuration = response.settings.animationDuration ?? 300;
      var showSplashScreen = response.settings.showSplashScreen ?? true;
      // 这个运算符的一个目的，就是跟?.配合使用，为null或undefined的值设置默认值
      var animationDuration = response.settings?.animationDuration ?? 300;
      /**
       * 上面代码中，如果response.setting是null或者undefined，
       * 或者response.settings.animationDuration是null或undefined
       * 就会返回默认值300。也就是说，这一行代码包括了两级属性的判断。
       */

      // 这个运算符很适合判断函数参数是否赋值。
      function Component(props) {
        const enable = props.enable ?? true;
      }
      // 上面代码判断props参数的enable属性是否赋值，基本等同于下面的写法
      function Component(props) {
        const { enable: enable = true } = props;
      }
      /**
     * ??本质上是逻辑运算，它与其他俩个逻辑运算符&&和||有一个优先级的问题，
     * 它们之间的优先级到底孰高孰低，优先级的不同，往往会导致逻辑运算符的结果不同。
     * 现在的规则是，如果多个逻辑运算符一起使用，必须用括号表明优先级，
     * 否则会报错。
     *
     * 以下是错误的写法：
     * lhs && middle ?? rhs
       lhs ?? middle && rhs
       lhs || middle ?? rhs
       lhs ?? middle || rhs


       下面是正确的写法
    */
      (lhs && middle) ?? rhs;
      lhs && (middle ?? rhs);

      (lhs ?? middle) && rhs;
      lhs ?? (middle && rhs);

      (lhs || middle) ?? rhs;
      lhs || (middle ?? rhs);

      (lhs ?? middle) || rhs;
      lhs ?? (middle || rhs);
    </script>
  </body>
</html>
